package com.loveprogrammer.eternity.model;

import com.loveprogrammer.eternity.common.Tuple;
import com.loveprogrammer.eternity.enums.AttackTypeEnum;
import com.loveprogrammer.eternity.enums.MonsterQualityEnum;
import com.loveprogrammer.eternity.enums.SkillQualityEnum;
import com.loveprogrammer.eternity.factory.SkillFactory;
import com.loveprogrammer.eternity.factory.template.CharacterTemplate;
import com.loveprogrammer.eternity.factory.template.HeroTemplate;
import com.loveprogrammer.eternity.factory.template.JobTemplate;
import com.loveprogrammer.eternity.model.attack.AttackEntity;
import com.loveprogrammer.eternity.model.attack.AttackResult;
import com.loveprogrammer.eternity.model.product.Coin;
import com.loveprogrammer.eternity.model.product.equipment.Equips;
import com.loveprogrammer.eternity.skill.Skill;
import com.loveprogrammer.eternity.skill.State;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @version 1.0.0
 * @description:
 * @author: eric
 * @date: 2022-08-02 16:41
 **/
public class Hero extends Character{

    private HeroTemplate template;

    public Hero(String name, int strength, int armature, int constitution, int magic, int technique, int speed,
                AtomicInteger hp, int hpMax, int baseStrength, int baseArmature, int baseConstitution, int baseMagic,
                int baseTechnique, int baseSpeed, int baseHp, int level, MonsterQualityEnum monsterQualityEnum,
                Integer currentExp, Integer nextLevelNeedExp, Equips equips,
                List<Skill> skills, List<State> states, int attackType, HeroTemplate template, int poisonResistance,
                int flameResistance, int thunderResistance,int iceResistance,int position) {
        super(template.getId(),name,strength,armature,constitution,magic,technique,speed,hp,hpMax,baseStrength,baseArmature,
                baseConstitution,baseMagic,baseTechnique,baseSpeed,baseHp,level,monsterQualityEnum,currentExp,
                nextLevelNeedExp,equips,skills,states,attackType,poisonResistance,flameResistance,thunderResistance,iceResistance,position);
        this.template = template;
    }


    public Hero(String name, HeroTemplate template) {
        super(template.getId(),name,0,template.getStrength(),template.getArmature(),template.getConstitution(),
                template.getMagic(),template.getTechnique(),template.getSpeed(),template.getAttackType(),template.getPoisonResistance(),
                template.getFlameResistance(), template.getThunderResistance(),template.getIceResistance(),template.getPosition());
        this.template = template;
    }

    @Override
    public int getDeadExp() {
        return 0;
    }

    @Override
    protected AttackEntity getHarm() {
        // 根据不同的英雄 力 法
        if(getAttackType() == 1) {
            return new AttackEntity(this.magic, AttackTypeEnum.MAGIC);
        }
        return new AttackEntity(this.strength, AttackTypeEnum.NORMAL);
    }

    @Override
    public void levelUp(int exp) {
        this.setLevel(this.level + 1);
        // 检查技能升级情况
        if(!this.getSkills().isEmpty()){
            this.getSkills().forEach(e -> {
                    e.levelUp(this.getLevel());

            });
        }
        // 是否可以习得新的技能
        String[] acquiredLevel = getTemplate().getAcquiredLevel().split(",");
        String[] skills = getTemplate().getSkills().split(",");
        String[] skillQualities = getTemplate().getSkillQuality().split(",");

        for (int i = 0; i < acquiredLevel.length; i++) {
            if (Integer.parseInt(acquiredLevel[i]) == getLevel()) {
                String skillId = skills[i];
                String skillQuality = skillQualities[i];
                try {
                    Skill skill = SkillFactory.getNewSkillById(skillId, SkillQualityEnum.getByCode(skillQuality));
                    if(skill != null) {
                        this.acquireSkill(skill);
                    }
                } catch (IOException | ClassNotFoundException e) {
                    e.printStackTrace();
                }
                break;
            }
        }


        // 属性增加
        this.setStrength(this.strength + template.getLevelUpStrength());
        this.setTechnique(this.technique + template.getLevelUpTechnique());
        this.setArmature(this.armature + template.getLevelUpArmature());
        this.setConstitution(this.constitution + template.getLevelUpConstitution());
        this.hp.addAndGet(10 * template.getLevelUpConstitution());
        this.hpMax = this.hp.get();
        this.setMagic(this.magic + template.getLevelUpMagic());
        // this.setTechnique(this.technique + template.getLevelUpTechnique());
        this.setSpeed(this.speed + template.getLevelUpSpeed());
        // 基础属性增加
        this.setBaseStrength(this.getBaseStrength() + template.getLevelUpStrength());
        this.setBaseTechnique(this.getBaseTechnique() + template.getLevelUpTechnique());
        this.setBaseArmature(this.getBaseArmature() + template.getLevelUpArmature());
        this.setBaseConstitution(this.getBaseConstitution() + template.getLevelUpConstitution());
        this.setBaseMagic(this.getBaseMagic() + template.getLevelUpMagic());
        // this.setBaseTechnique(this.technique);
        this.setBaseSpeed(this.getBaseSpeed() + template.getLevelUpSpeed());

        // 计算下一级需要的经验值
        int needExp = this.setNextLevelNeedExp();
        if(exp > needExp){
            levelUp(exp);
        }
    }

    @Override
    public void reset() {
        // 根据级别重新计算英雄的属性值
    }

    @Override
    public Tuple<String,List<Character>> attack(List<? extends Character> characters) {
        Tuple<String,List<Character>> result = new Tuple<>();
        ArrayList<Character> defences = new ArrayList<>();
        // 已经阵亡的加入返回列表
//        List<Character> deadList = characters.stream().filter(Character::checkDead).collect(Collectors.toList());
//        if(deadList.size() > 0) {
//            defences.addAll(deadList);
//        }
        List<Character> list = characters.stream().filter(e  -> !e.checkDead()).collect(Collectors.toList());
        StringBuilder builder = new StringBuilder();
        if(list.size() > 0) {
            // 普通攻击， 按照血量排序，攻击血量最低的
            Character defence = findSingleAttacker(list,true);
            builder.append(this.name).append("(").append(getCurrentHp()).append("/")
                    .append(getHpMax()).append(")").append("攻击了").append(defence.getName());
            AttackEntity harm = getHarm();
            // 暴击检测
            boolean crit = critCheck(this);
            if(crit) {
                harm.setHarm(critPower(harm.getHarm()));
            }
            AttackResult attackResult = defence.defence(harm);
            computeHarm(builder,crit,defence,attackResult,this,null,defences);
            defences.add(defence);
        }
        result.setKey(builder.toString());
        result.setValue(defences);
        return result;
    }

    public HeroTemplate getTemplate() {
        return template;
    }

    public void setTemplate(HeroTemplate template) {
        this.template = template;
    }


    @Override
    public Coin sale() {
        return new Coin();
    }

    // 转职
    public void transfer(JobTemplate jobTemplate) throws IOException, ClassNotFoundException {
        // 首先要替换到自己的模板
        setTemplate(HeroTemplate.newInstance(jobTemplate));
        // 自身的属性增加
        this.setBaseStrength(this.getBaseStrength() + jobTemplate.getStrength());
        this.setBaseConstitution(this.getBaseConstitution() + jobTemplate.getArmature());
        this.setBaseTechnique(this.getBaseTechnique() + jobTemplate.getTechnique());
        this.setBaseSpeed(this.getBaseSpeed() + jobTemplate.getSpeed());
        this.setBaseMagic(this.getBaseMagic() + jobTemplate.getMagic());
        this.setBaseConstitution(this.getBaseConstitution() + jobTemplate.getConstitution());
        this.setBaseHp(this.getBaseHp() + jobTemplate.getConstitution() * 10);
        // 自身的属性增加
        this.setStrength(this.getStrength() + jobTemplate.getStrength());
        this.setArmature(this.getArmature() + jobTemplate.getArmature());
        this.setTechnique(this.getTechnique() + jobTemplate.getTechnique());
        this.setSpeed(this.getSpeed() + jobTemplate.getSpeed());
        this.setMagic(this.getMagic() + jobTemplate.getMagic());
        this.setConstitution(this.getConstitution() + jobTemplate.getConstitution());
        this.hp().addAndGet(jobTemplate.getConstitution() * 10);
        this.hpMax = this.hp.get();

        this.setFlameResistance(this.getFlameResistance() + jobTemplate.getFlameResistance());
        this.setIceResistance(this.getIceResistance() + jobTemplate.getIceResistance());
        this.setThunderResistance(this.getThunderResistance() + jobTemplate.getThunderResistance());
        this.setPoisonResistance(this.getPoisonResistance() + jobTemplate.getPoisonResistance());

        // 技能也要跟着升级或者修改
        String[] newSkills = jobTemplate.getNewSkills().split(",");
        String[] skillQualities = jobTemplate.getSkillQuality().split(",");
        String[] acquiredLevels = jobTemplate.getAcquiredLevel().split(",");

        // 用新的技能替换掉老的技能
        List<Skill> skills = new ArrayList<>();
        for (int i = 0; i < newSkills.length; i++) {
            int acquiredLevel = Integer.parseInt(acquiredLevels[i]);
            if(acquiredLevel <= getLevel()){
                Skill skill = SkillFactory.getNewSkillById(newSkills[i], SkillQualityEnum.getByCode(skillQualities[i]));
                // 设定等级
                skill.setLevel(1);
                skill.levelUpInit(getLevel(),acquiredLevel);
                skills.add(skill);
            }
        }
        setSkills(skills);
    }
}
